home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c++-part1 / 5259 < prev    next >
Encoding:
Text File  |  1996-08-05  |  4.1 KB  |  176 lines

  1. Path: magnus.acs.ohio-state.edu!csn!ub!newserve!rebecca!rpi!not-for-mail
  2. From: Richard Wells <rdwells@mmm.com>
  3. Newsgroups: comp.lang.c++,comp.lang.c++.moderated,comp.lang.c.moderated
  4. Subject: Re: Q: Rigorous coding using #if !defined(...) and #include
  5. Date: 2 Feb 1996 16:08:28 -0000
  6. Organization: 3M Company
  7. Sender: cppmods@netlab.cs.rpi.edu
  8. Approved: devitto@ferndown.ate.slb.com
  9. Message-ID: <4etcts$l50@netlab.cs.rpi.edu>
  10. References: <4eo1fs$rr3@netlab.cs.rpi.edu>
  11. NNTP-Posting-Host: netlab.cs.rpi.edu
  12. X-Original-Date: Fri, 02 Feb 1996 09:43:24 -0600
  13.  
  14. (I see the moderator(s) allowed the crossposting for the
  15. first message, so I'll keep the full list of newsgroups.
  16. I would argue that this applies to C as well as C++ if you
  17. just replace "class" with "struct" in the code below and
  18. make the other obvious necessary syntactical changes.)
  19.  
  20. David Carr wrote:
  21. > In header files, I have used the notation;
  22. > #if !defined (__MYCLASS_H)
  23. > #define (__MYCLASS_H)
  24. > #include "Other.h"
  25. > class MyClass
  26. > {
  27. >         ...// Uses something in Other.h
  28. > };
  29. > #endif
  30. > The problem is this.  I have another class;
  31. > #if !defined (__OTHER_H)
  32. > #define (__OTHER_H)
  33. > #include "MyClass.h"
  34. > class Other
  35. > {
  36. >         ...// Uses something in MyClass.h
  37. > };
  38. > #endif
  39. > and in my source for MyClass.cpp, MyClass.h is obviously
  40. > included.  Now,
  41. > when I try to compile MyClass.cpp, MyClass.h is included and
  42. > __MYCLASS_H
  43. > becomes defined.  Then, MyClass.h #includes Other.h, thus
  44. > defining __OTHER_H.
  45. > Now, Other.h #includes MyClass.h.  As __MYCLASS_H has already
  46. > been defined,
  47. > the code in MyClass.h is not included.  Returning to Other.h,
  48. > this code
  49. > references something in MyClass.h (i.e. its class) and a
  50. > compiler error is
  51. > generated because the symbol/identifier/whatever is unknown.
  52. > What is the preferred method for writing rigorous code and
  53. > solving this
  54. > problem?
  55. > Any suggestions as to how to make H files a complete interface?
  56.  
  57. I find that this can generally be avoided by taking advantage
  58. of the fact that you can use pointers to incomplete types (someone
  59. please correct me if this not the proper C/C++ terminology).  For
  60. example, to flesh out your example a little:
  61.  
  62.   #if !defined (__MYCLASS_H)
  63.   #define (__MYCLASS_H)
  64.  
  65.   #include "Other.h"
  66.  
  67.   class MyClass
  68.   {
  69.       Other *foo;
  70.   };
  71.  
  72.   #endif
  73.  
  74. and in another header
  75.  
  76.   #if !defined (__OTHER_H)
  77.   #define (__OTHER_H)
  78.  
  79.   #include "MyClass.h"
  80.  
  81.   class Other
  82.   {
  83.       MyClass *bar;
  84.   };
  85.  
  86.   #endif
  87.  
  88. The #include statements within the headers can be replaced
  89. by "class Other;" and "class MyCLass;", to get:
  90.  
  91.   #if !defined (__MYCLASS_H)
  92.   #define (__MYCLASS_H)
  93.  
  94.   class Other; // #include replaced by incomplete type
  95.  
  96.   class MyClass
  97.   {
  98.       Other *foo;
  99.   };
  100.  
  101.   #endif
  102.  
  103. and
  104.  
  105.   #if !defined (__OTHER_H)
  106.   #define (__OTHER_H)
  107.  
  108.   class MyClass; // #include replaced by incomplete type
  109.  
  110.   class Other
  111.   {
  112.       MyClass *bar;
  113.   };
  114.  
  115.   #endif
  116.  
  117. I have yet to run into circumstances where this does not
  118. avoid the situation.
  119.  
  120. In fact, I tend to use incomplete types wherever possible
  121. in place of #include.  It keeps compile times down a little,
  122. and IMHO provides for better information hiding.  That is,
  123. in the above example, class Other needs to know that class
  124. MyClass exists, but probably shouldn't be privy to its
  125. internal details, so shouldn't need to #include its header.
  126.  
  127. Just to bore y'all a little longer, if one of the classes
  128. actually contains an instance of the other rather than a
  129. pointer to an instance, than it is necessary to include
  130. the proper header.  For example:
  131.  
  132.   #if !defined (__MYCLASS_H)
  133.   #define (__MYCLASS_H)
  134.  
  135.   class Other;
  136.  
  137.   class MyClass
  138.   {
  139.       Other *foo; // still a pointer
  140.   };
  141.  
  142.   #endif
  143.  
  144. and
  145.  
  146.   #if !defined (__OTHER_H)
  147.   #define (__OTHER_H)
  148.  
  149.   #include "MyClass.h" // need the full definition
  150.  
  151.   class Other
  152.   {
  153.       MyClass bar; // NOT a pointer
  154.   };
  155.  
  156.   #endif
  157.  
  158. Hope this helps.
  159.  
  160.       [ Articles to moderate: mailto:c++-submit@netlab.cs.rpi.edu ]
  161.       [  Read the C++ FAQ: http://www.connobj.com/cpp/cppfaq.htm  ]
  162.       [  Moderation policy: http://www.connobj.com/cpp/guide.htm  ]
  163.       [      Comments? mailto:c++-request@netlab.cs.rpi.edu       ]
  164.